home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / editors / mjovesrc.zoo / disp.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  30KB  |  1,493 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include "termcap.h"
  11. #include "chars.h"
  12. #include "fp.h"
  13. #include "disp.h"
  14. #ifdef    IPROCS
  15. # include "iproc.h"
  16. #endif
  17.  
  18. #ifdef    MAC
  19. # include "mac.h"
  20. #else
  21. # ifdef    STDARGS
  22. #  include <stdarg.h>
  23. # else
  24. #  include <varargs.h>
  25. # endif
  26. # include <sys/stat.h>
  27. #endif
  28.  
  29. #include <signal.h>
  30.  
  31. private void
  32. #ifdef    ID_CHAR
  33.     DeTab proto((int, char *, char *, size_t, int)),
  34.     DelChar proto((int, int, int)),
  35.     InsChar proto((int, int, int, char *)),
  36. #endif
  37.     DoIDline proto((int)),
  38.     do_cl_eol proto((int)),
  39.     ModeLine proto((Window *)),
  40.     GotoDot proto((void)),
  41.     UpdLine proto((int)),
  42.     UpdWindow proto((Window *, int));
  43.  
  44. #ifdef    MSDOS
  45. extern void    dobell proto((int x));
  46. #else
  47. private void    dobell proto((int x));
  48. #endif
  49.  
  50. #ifdef    ID_CHAR
  51. private bool
  52.     IDchar proto ((char *, int, int)),
  53.     OkayDelete proto ((int, int, int)),
  54.     OkayInsert proto ((int, int));
  55. private int
  56.     NumSimilar proto ((char *, char *, int)),
  57.     IDcomp proto ((char *, char *, int));
  58. #endif
  59. private int
  60.     AddLines proto((int, int)),
  61.     DelLines proto((int, int));
  62.  
  63.  
  64.  
  65. int    DisabledRedisplay = NO;
  66.  
  67. /* Kludge windows gets called by the routines that delete lines from the
  68.    buffer.  If the w->w_line or w->w_top are deleted and this procedure
  69.    is not called, the redisplay routine will barf. */
  70.  
  71. void
  72. ChkWindows(line1, line2)
  73. Line    *line1,
  74.     *line2;
  75. {
  76.     register Window    *w = fwind;
  77.     register Line    *lp,
  78.             *lend = line2->l_next;
  79.  
  80.     do {
  81.         if (w->w_bufp == curbuf) {
  82.             for (lp = line1->l_next; lp != lend; lp = lp->l_next) {
  83.                 if (lp == w->w_top)
  84.                     w->w_flags |= W_TOPGONE;
  85.                 if (lp == w->w_line)
  86.                     w->w_flags |= W_CURGONE;
  87.             }
  88.         }
  89.         w = w->w_next;
  90.     } while (w != fwind);
  91. }
  92.  
  93. /* Deleted and killed Lines are about to be recycled: check for dangling refs */
  94.  
  95. void
  96. ChkWinLines()
  97. {
  98.     register Window    *w = fwind;
  99.  
  100.     do {
  101.         if (w->w_top == NULL || w->w_top->l_dline == NULL_DADDR)
  102.             w->w_flags |= W_TOPGONE;
  103.         if (w->w_line == NULL || w->w_line->l_dline == NULL_DADDR)
  104.             w->w_flags |= W_CURGONE;
  105.         w = w->w_next;
  106.     } while (w != fwind);
  107. }
  108.  
  109. private bool    RingBell;    /* So if we have a lot of errors ...
  110.                   ring the bell only ONCE */
  111.  
  112. void
  113. redisplay()
  114. {
  115.     register Window    *w = fwind;
  116.     int    lineno,
  117.         done_ID = NO,
  118.         i;
  119.     register struct scrimage    *des_p,
  120.                     *phys_p;
  121.  
  122.     if (DisabledRedisplay == YES)
  123.         return;
  124.     curwind->w_line = curwind->w_bufp->b_dot;
  125.     curwind->w_char = curwind->w_bufp->b_char;
  126. #ifdef    MAC
  127.     InputPending = NO;
  128. #else
  129.     if ((InputPending = charp()) != NO)    /* calls CheckEvent, which could */
  130.         return;    /* result in a call to rediplay(). We don't want that. */
  131. #endif
  132. #ifdef    BSD_SIGS
  133.     if (UpdFreq)
  134.         SigHold(SIGALRM);
  135. #endif
  136.     if (RingBell) {
  137.         dobell(1);
  138.         RingBell = NO;
  139.     }
  140.     AbortCnt = BufSize;        /* initialize this now */
  141.     if (UpdMesg)
  142.         DrawMesg(YES);
  143.  
  144.     for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
  145.         UpdWindow(w, lineno);
  146.         lineno += w->w_height;
  147.     }
  148.  
  149.     UpdModLine = NO;/* Now that we've called update window, we can
  150.                assume that the modeline will be updated.  But
  151.                if while redrawing the modeline the user types
  152.                a character, ModeLine() is free to set this on
  153.                again so that the modeline will be fully drawn
  154.                at the next redisplay. */
  155.  
  156.     des_p = DesiredScreen;
  157.     phys_p = PhysScreen;
  158.     for (i = 0; i < ILI; i++, des_p++, phys_p++) {
  159.         if (!done_ID && (des_p->s_id != phys_p->s_id)) {
  160.             DoIDline(i);
  161.             done_ID = YES;
  162.         }
  163.         if ((des_p->s_flags & (DIRTY | L_MOD)) ||
  164.             (des_p->s_id != phys_p->s_id) ||
  165.             (des_p->s_vln != phys_p->s_vln) ||
  166.             (des_p->s_offset != phys_p->s_offset))
  167.             UpdLine(i);
  168.         if (InputPending)
  169.             goto ret;
  170.     }
  171.  
  172.     if (Asking) {
  173.         Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, AskingWidth)));
  174.             /* Nice kludge */
  175.         flushscreen();
  176.     } else {
  177.         GotoDot();
  178.     }
  179. ret:
  180.     ;    /* yuck */
  181.  
  182. #ifdef    BSD_SIGS
  183.     if (UpdFreq)
  184.         SigRelse(SIGALRM);
  185. #endif
  186. #ifdef    MAC
  187.     if (Windchange)
  188.         docontrols();
  189. #endif    /* MAC */
  190. }
  191.  
  192. #ifndef    IBMPC
  193. private void
  194. dobell(n)
  195. int    n;
  196. {
  197.     while (--n >= 0) {
  198. #ifndef    MAC
  199.         if (VisBell && VB)
  200.             putstr(VB);
  201.         else
  202.             putpad(BL, 1);
  203. #else
  204.         SysBeep(5);
  205. #endif
  206.     }
  207.     flushscreen();
  208. }
  209. #endif    /* IBMPC */
  210.  
  211. /* find_pos() returns the position on the line, that C_CHAR represents
  212.    in LINE */
  213.  
  214. private int
  215. find_pos(line, c_char)
  216. Line    *line;
  217. int    c_char;
  218. {
  219.     return calc_pos(lcontents(line), c_char);
  220. }
  221.  
  222. int
  223. calc_pos(lp, c_char)
  224. register char    *lp;
  225. register int    c_char;
  226. {
  227.     register int    pos = 0;
  228.     register int    c;
  229.  
  230.  
  231.     while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) {
  232.         if (c == '\t')
  233.             pos += (tabstop - (pos % tabstop));
  234.         else if (jiscntrl(c))
  235.             pos += 2;
  236.         else
  237.             pos += 1;
  238.     }
  239.     return pos;
  240. }
  241.  
  242. bool    UpdModLine = NO,
  243.     UpdMesg = NO;
  244.  
  245. private void
  246. DoIDline(start)
  247. int    start;
  248. {
  249.     register struct scrimage    *des_p = &DesiredScreen[start];
  250.     struct scrimage    *phys_p = &PhysScreen[start];
  251.     register int    i,
  252.             j;
  253.  
  254.     /* Some changes have been made.  Try for insert or delete lines.
  255.        If either case has happened, Addlines and/or DelLines will do
  256.        necessary scrolling, also CONVERTING PhysScreen to account for the
  257.        physical changes.  The comparison continues from where the
  258.        insertion/deletion takes place; this doesn't happen very often,
  259.        usually it happens with more than one window with the same
  260.        buffer. */
  261.  
  262.     if (!CanScroll)
  263.         return;        /* We should never have been called! */
  264.  
  265.     for (i = start; i < ILI; i++, des_p++, phys_p++)
  266.         if (des_p->s_id != phys_p->s_id)
  267.             break;
  268.  
  269.     for (; i < ILI; i++) {
  270.         for (j = i + 1; j < ILI; j++) {
  271.             des_p = &DesiredScreen[j];
  272.             phys_p = &PhysScreen[j];
  273.             if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
  274.                 break;
  275.             if (des_p->s_id == PhysScreen[i].s_id) {
  276.                 if (des_p->s_id == 0)
  277.                     continue;
  278.                 if (AddLines(i, j - i)) {
  279.                     DoIDline(j);
  280.                     return;
  281.                 }
  282.                 break;
  283.             }
  284.             if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
  285.                 if (des_p->s_id == 0)
  286.                     continue;
  287.                 if (DelLines(i, j - i)) {
  288.                     DoIDline(i);
  289.                     return;
  290.                 }
  291.                 break;
  292.             }
  293.         }
  294.     }
  295. }
  296.  
  297. /* Make DesiredScreen reflect what the screen should look like when we are done
  298.    with the redisplay.  This deals with horizontal scrolling.  Also makes
  299.    sure the current line of the Window is in the window. */
  300.  
  301. bool    ScrollAll = NO;
  302.  
  303. private void
  304. UpdWindow(w, start)
  305. register Window    *w;
  306. int    start;
  307. {
  308.     Line    *lp;
  309.     int    i,
  310.         upper,        /* top of window */
  311.         lower,        /* bottom of window */
  312.         strt_col,    /* starting print column of current line */
  313.         ntries = 0;    /* # of tries at updating window */
  314.     register struct scrimage    *des_p,
  315.                     *phys_p;
  316.     Buffer    *bp = w->w_bufp;
  317.  
  318. retry:
  319.     if (w->w_flags & W_CURGONE) {
  320.         w->w_line = bp->b_dot;
  321.         w->w_char = bp->b_char;
  322.     }
  323.     if (w->w_flags & W_TOPGONE)
  324.         CentWind(w);    /* reset topline of screen */
  325.     w->w_flags &= ~(W_CURGONE | W_TOPGONE);
  326.  
  327.     /* make sure that the current line is in the window */
  328.     upper = start;
  329.     lower = upper + w->w_height - 1;    /* don't include modeline */
  330.     for (i = upper, lp = w->w_top; i < lower && lp != NULL; lp = lp->l_next, i++)
  331.         if (lp == w->w_line)
  332.             break;
  333.     if (i == lower || lp == NULL) {
  334.         ntries += 1;
  335.         if (ntries == 1) {
  336.             CalcWind(w);
  337.             goto retry;
  338.         } else if (ntries == 2) {
  339.             w->w_top = w->w_line = w->w_bufp->b_first;
  340.             writef("\rERROR in redisplay: I got hopelessly lost!");
  341.             dobell(2);
  342.             goto retry;
  343.         } else if (ntries == 3) {
  344.             writef("\n\rOops, still lost, quitting ...\r\n");
  345.             finish(SIGHUP);
  346.         }
  347.     }
  348.  
  349.     /* first do some calculations for the current line */
  350.     {
  351.         int    diff = (w->w_flags & W_NUMLINES) ? 8 : 0,
  352.             end_col;
  353.  
  354.         strt_col = ScrollAll? w->w_LRscroll : PhysScreen[i].s_offset;
  355.         end_col = strt_col + (CO - 2) - diff;
  356.         /* Right now we are displaying from strt_col to
  357.            end_col of the buffer line.  These are PRINT
  358.            columns, not actual characters. */
  359.         w->w_dotcol = find_pos(w->w_line, w->w_char);
  360.         /* if the new dotcol is out of range, res